from django.http import JsonResponse
from django.views import View
from django_redis import get_redis_connection
from apps.goods.models import SKU
from apps.users.models import Address
from utils.views import LoginRequiredJSONMixin


################订单结算显示页面####################
class OrderSettlementView(LoginRequiredJSONMixin, View):
    def get(self, request):
        user = request.user
        addresses = Address.objects.filter(is_deleted=False)
        addresses_list = []
        for address in addresses:
            addresses_list.append({
                'id': address.id,
                'province': address.province.name,
                'city': address.city.name,
                'district': address.district.name,
                'place': address.place,
                'receiver': address.receiver,
                'mobile': address.mobile,
            })

        # 连接 Redis 数据库
        redis_cli = get_redis_connection('carts')
        pipeline = redis_cli.pipeline()
        pipeline.hgetall('carts_%s' % user.id)
        pipeline.smembers('selected_%s' % user.id)
        result = pipeline.execute()
        sku_id_counts = result[0]  # {b'1': b'2', b'2': b'3'}
        selected_ids = result[1]  # {b'1', b'2'}

        # 用字典存储选中的商品和数量
        selected_carts = {}
        for sku_id in selected_ids:
            sku_id_int = int(sku_id.decode())  # b'1' -> 1
            count = int(sku_id_counts[sku_id].decode())  # b'2' -> 2
            selected_carts[sku_id_int] = count

        # 查询商品详细信息
        sku_list = []
        for sku_id, count in selected_carts.items():
            sku = SKU.objects.get(pk=sku_id)
            sku_list.append({
                'id': sku.id,
                'name': sku.name,
                'count': count,
                'default_image_url': sku.default_image.url,
                'price': sku.price
            })

        # 运费
        from decimal import Decimal
        freight = Decimal('10')
        context = {
            'skus': sku_list,
            'addresses': addresses_list,
            'freight': freight
        }

        return JsonResponse({'code': 0, 'errmsg': 'ok', 'context': context})


########提交订单##########
import json
from apps.orders.models import OrderInfo, OrderGoods
from django.db import transaction


class OrderCommitView(LoginRequiredJSONMixin, View):

    def post(self, request):
        user = request.user
        # 一。接收请求     user,address_id,pay_method
        data = json.loads(request.body.decode())
        address_id = data.get('address_id')
        pay_method = data.get('pay_method')

        # 二。验证数据
        if not all([address_id, pay_method]):
            return JsonResponse({'code': 400, 'errmsg': '参数不全'})

        try:
            address = Address.objects.get(id=address_id)
        except Address.DoesNotExist:
            return JsonResponse({'code': 400, 'errmsg': '参数不正确'})

        # if pay_method not in [1,2]:   这么写是没有问题的。
        # 从代码的可读性来说很差。 我都不知道 1 什么意思 2 什么意思

        if pay_method not in [OrderInfo.PAY_METHODS_ENUM['CASH'], OrderInfo.PAY_METHODS_ENUM['ALIPAY']]:
            return JsonResponse({'code': 400, 'errmsg': '参数不正确'})
        # order_id 主键（自己生成）   年月日时分秒 + 用户id（9位数字）
        from django.utils import timezone
        # from datetime import datetime
        # datetime.strftime()
        # Year
        # month
        # day
        # Hour
        # Minute
        # Second
        # %f 微秒
        # timezone.localtime() 2020-10-19 10:03:10
        order_id = timezone.localtime().strftime('%Y%m%d%H%M%S%f') + '%09d' % user.id

        # 支付状态由支付方式决定
        # 代码是对的。可读性差
        # if pay_method == 1: # 货到付款
        #     pay_status=2
        # else:
        #     pay_status=1

        if pay_method == OrderInfo.PAY_METHODS_ENUM['CASH']:
            status = OrderInfo.ORDER_STATUS_ENUM['UNSEND']
        else:
            status = OrderInfo.ORDER_STATUS_ENUM['UNPAID']

        # 总数量，总金额， = 0
        total_count = 0
        from decimal import Decimal
        total_amount = Decimal('0')  #总金额
        # 运费
        freight = Decimal('10.00')

        with transaction.atomic():

            # 事务开始点
            point = transaction.savepoint()

            # 三。数据入库     生成订单（订单基本信息表和订单商品信息表）
            #     1.先保存订单基本信息
            orderinfo = OrderInfo.objects.create(
                order_id=order_id,
                user=user,
                address=address,
                total_count=total_count,
                total_amount=total_amount,
                freight=freight,
                pay_method=pay_method,
                status=status
            )
            #     2 再保存订单商品信息
            #       2.1 连接redis
            redis_cli = get_redis_connection('carts')
            #       2.2 获取hash
            sku_id_counts = redis_cli.hgetall('carts_%s' % user.id)
            #       2.3 获取set
            selected_ids = redis_cli.smembers('selected_%s' % user.id)
            #       2.4 遍历选中商品的id，
            carts = {}
            #         最好重写组织一个数据，这个数据是选中的商品信息
            #         {sku_id:count,sku_id:count}
            for sku_id in selected_ids:
                carts[int(sku_id)] = int(sku_id_counts[sku_id])

            ##         {sku_id:count,sku_id:count}
            #       2.5 遍历
            for sku_id, count in carts.items():

                # for i in range(10):
                while True:
                    # 根据选中商品的id进行查询
                    sku = SKU.objects.get(id=sku_id)
                    #       2.6 判断库存是否充足
                    if sku.stock < count:
                        #回滚点
                        transaction.savepoint_rollback(point)

                        #       2.7 如果不充足，下单失败
                        return JsonResponse({'code': 400, 'errmsg': '库存不足'})

                    from time import sleep
                    sleep(7)
                    #       2.8 如果充足，则库存减少，销量增加
                    # sku.stock -= count
                    # sku.sales += count
                    # sku.save()  #记得保存

                    # 1. 先记录某一个数据    记录哪个数据都可以
                    #旧库存  我们参照这个记录
                    old_stock = sku.stock

                    # 2. 我更新的时候，再比对一下这个记录对不对
                    new_stock = sku.stock - count
                    new_sales = sku.sales + count

                    result = SKU.objects.filter(id=sku_id, stock=old_stock).update(stock=new_stock, sales=new_sales)
                    # result = 1 表示 有1条记录修改成功
                    # result = 0 表示 没有更新

                    if result == 0:
                        # sleep(0.005)
                        continue
                        # 暂时回滚和返回下单失败
                        # transaction.savepoint_rollback(point)
                        # return JsonResponse({'code':400,'errmsg':'下单失败~~~~~~~'})

                    #       2.9 累加总数量和总金额
                    orderinfo.total_count += count
                    orderinfo.total_amount += (count * sku.price)

                    #       2.10 保存订单商品信息
                    OrderGoods.objects.create(
                        order=orderinfo,
                        sku=sku,
                        count=count,
                        price=sku.price
                    )
                    break
            #   3.更新订单的总金额和总数量
            orderinfo.save()
            # 提交点
            transaction.savepoint_commit(point)

        #   4.将redis中选中的商品信息移除出去 （暂缓）
        # 四。返回响应
        return JsonResponse({'code': 0, 'errmsg': 'ok', 'order_id': order_id})
